﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Data.Common;

namespace SDL
{
    public class ConnectionManager
    {
        #region Connection
        private static int num = 0;

        internal static List<SDLDbConnection> _Connections = new List<SDLDbConnection>();

        public static SDLDbConnection getFreeConnection()
        {
            if (_Connections.Count == 0) return null;
            return (from item in _Connections where !item.Locked select item).FirstOrDefault();
        }

        public SDLDbConnection Connection
        {
            [MethodImpl(MethodImplOptions.Synchronized)]
            get
            {
                if (_ConnectionString == null)
                    throw new Exception("ConnectionString not initializate!");

                var _Connection = getFreeConnection();
                if (_Connection == null)
                {
                    _Connection = new SDLDbConnection(_DataBase.CreateConnection());
                    _Connection.ConnectionString = _ConnectionString;
                    _Connection.Dirty = (num++ >= 5);
                    _Connection.Index = num;
                    _Connection.Connection.Open();
                    _Connection.OnFree += new SDLDbConnection.dOnFree(_Connection_OnFree);
                    _Connections.Add(_Connection);
                }
                if (_Connection.State == System.Data.ConnectionState.Closed ||
                    _Connection.State == System.Data.ConnectionState.Broken)
                    _Connection.Open();
                return (_Connection);
            }
        }

        void _Connection_OnFree(SDLDbConnection connection)
        {
            if (connection.Dirty)
            {
                num--;
                var itm = (from item in _Connections where item.Index == connection.Index select item).FirstOrDefault();
                if (itm.Connection.State != System.Data.ConnectionState.Closed)
                    itm.Close();
                _Connections.Remove(itm);
            }
        }

        public static void Free(DbConnection connection)
        {
            var itm = (from item in _Connections where item.Connection.Equals(connection) select item).FirstOrDefault();
            if (itm != null) itm.Free();
        }
        #endregion

        #region ConnectionString
        private static ConnectionString _ConnectionString = null;

        public ConnectionString ConnectionString
        {
            get { return (_ConnectionString); }
        }

        public static ConnectionString getConnectionString
        {
            get { return (_ConnectionString); }
        }
        #endregion

        #region DataBase
        private static DbProviderFactory _DataBase = null;

        public DbProviderFactory DataBase
        {
            get { return (_DataBase); }
        }
        #endregion

        public ConnectionManager() { }

        public ConnectionManager(ConnectionString cs)
        {
            //if (_ConnectionString != null)
            //	throw new Exception("ConnectionString already initializate!");

            _DataBase = DbProviderFactories.GetFactory(cs.Provider);
            _ConnectionString = cs;
        }

        public static void CloseConnection()
        {
            _Connections.ForEach(item =>
                {
                    if (item.State != System.Data.ConnectionState.Closed)
                        item.Close();
                });
        }
    }
}
